/**
 * Copyright (c) 2010 Jesco Freund.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of Backtory nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *  $Id$
 */


#ifndef __LIBYAR_MACROS_H
#define __LIBYAR_MACROS_H

/* make available O_* flags */
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <libyar/types.h>
#include <libyar/defaults.h>
#include <libyar/init.h>
#include <libyar/unicode.h>


/**
 * Macro to initialize YAR library
 */
#define YAR_init() { \
	yar_init(); \
}


/**
 * Macro to initialize a YAR handle
 */
#define YAR_fh_init(handle) { \
	(handle)->fn = 				NULL;							\
	(handle)->fd = 				-1;								\
	(handle)->version = 		LIBYAR_VERSION_NUM;				\
	(handle)->compression = 	LIBYAR_COMPRESS_DEFAULT;		\
	(handle)->encryption = 		LIBYAR_ENCRYPT_DEFAULT;			\
	(handle)->digest = 			LIBYAR_DIGEST_DEFAULT;			\
	(handle)->encrypt_mdt = 	LIBYAR_ENCRYPT_MDT_DEFAULT;		\
	(handle)->compress_mdt = 	LIBYAR_COMPRESS_MDT_DEFAULT;	\
	(handle)->encrypt_fmd = 	LIBYAR_ENCRYPT_FMD_DEFAULT;		\
	(handle)->compress_fmd = 	LIBYAR_COMPRESS_FMD_DEFAULT;	\
	(handle)->digest_fmd = 		LIBYAR_DIGEST_FMD_DEFAULT;		\
	(handle)->encrypt_fcd = 	LIBYAR_ENCRYPT_FCD_DEFAULT;		\
	(handle)->compress_fcd = 	LIBYAR_COMPRESS_FCD_DEFAULT;	\
	(handle)->digest_fcd = 		LIBYAR_DIGEST_FCD_DEFAULT;		\
	(handle)->encrypt_fi = 		LIBYAR_ENCRYPT_FI_DEFAULT;		\
	(handle)->compress_fi = 	LIBYAR_COMPRESS_FI_DEFAULT;		\
	(handle)->dataoffset = 		32;								\
	(handle)->indexoffset = 	32;								\
}


/**
 * Macro to check whether a YAR file is empty.
 * Returns true also for freshly initialized YAR handles which are
 * not yet bound to a physical file on the file system. 
 */
#define YAR_fh_isempty(handle) ((handle)->dataoffset == (handle)->indexoffset == 32)


/**
 * Macro to check whether a YAR handle is bound to a physical file
 * on the file system.
 */
#define YAR_fh_isopen(handle)  (((handle)->fn != NULL) && ((handle)->fd != -1))


/**
 * Macro to create a YAR file with the given filename and
 * connected to the specified handle.
 *
 * Always use this macro to create a new YAR file; never
 * use the yar_create() directly!
 */
#define YAR_fh_create(handle, filename, mode) { \
	(handle)->fn = malloc(strlen((filename)) + 1); \
	strncpy((handle)->fn, filename, strlen((filename)) + 1); \
	yar_create((handle), (filename), (mode)); \
}


/**
 * Macro to close a YAR file handle.
 *
 * Always use this macro to close a YAR file; never
 * use the yar_close() directly!
 */
#define YAR_close(handle) { \
	yar_close((handle)); \
	free((handle)->fn); \
	(handle)->fn = NULL; \
	(handle)->fd = -1; \
}


/**
 * Macro to initialize a meta data table recordset
 */
#define YAR_mdt_record_init(mdr) { \
	(mrd)->size = 0; \
	(mdr)->len = 0; \
	(mdr)->name = NULL; \
}


/**
 * Macro to initialize a meta data table structure
 */
#define YAR_mdt_init(mdt) { \
	(mdt)->listv = NULL; \
	(mdt)->listc = 0; \
}


/**
 * Macro to append to a meta data table structure
 */
#define YAR_mdt_append(mdt, size, len, name, charset) { \
	size_t __mdt_append_len; \
	yar_unicode_ucsize((name), (len), (charset), &__mdt_append_len); \
	(mdt)->listc++; \
	if (mdt->listc == 1) { \
		(mdt)->listv = (yar_mdt_record_t *)malloc(sizeof(yar_mdt_record_t)); \
	} \
	else { \
		(mdt)->listv = (yar_mdt_record_t *)realloc((mdt)->listv, sizeof(yar_mdt_record_t) * (mdt)->listc); \
	} \
	(mdt)->listv[(mdt)->listc - 1].size = (size); \
	(mdt)->listv[(mdt)->listc - 1].len = (len); \
	(mdt)->listv[(mdt)->listc - 1].name = (unsigned char *)malloc(__mdt_append_len + 1); \
	yar_unicode_convert((name), (len), (charset), (mdt)->listv[(mdt)->listc - 1].name, __mdt_append_len + 1); \
}


/**
 * Macro to initialize a file list data structure
 */
#define YAR_flist_init(flist) { \
	(flist)->listv = NULL; \
	(flist)->listc = 0; \
}

#endif /* __LIBYAR_MACROS_H */
